#ifndef ZQFUNCTION_H
#define ZQFUNCTION_H

#include <QObject>
#include <QDebug>
#include <QTimer>
#include <QTime>
#include <QDir>
#include <QEventLoop>
#include <math.h>
#include "zqopencv.h"

#if(QT_VERSION >= QT_VERSION_CHECK(5,15,2))
#include <QElapsedTimer>
#endif

#ifdef  Q_CC_GNU
#include <sys/time.h>
#endif

namespace zgq{
class ZQFunction
{
public:
    explicit ZQFunction(){};
    virtual ~ZQFunction(){};

    //1.延时函数毫秒级
    /** @brief 延时函数毫秒级*/
    void delayMs(int ms);//延时函数毫秒级
    //2.计时
    //2.1 程序计时Ms
    /** @brief 计时器开始，毫秒级*/
    void startTimerMs();//计时器，与startTimerMs()搭配使用
    /** @brief 计时器结束*/
    double endTimerMs();//计时器，与endTimerMs()搭配使用
private:
    QElapsedTimer m_Time;

    //2.2 程序计时S
public:
    /** @brief 计时器开始，秒级别*/
    void startClockMs();//计时器，与endClockMs()搭配使用
    /** @brief 计时器结束，秒级别*/
    double endClockMs();//计时器，与startClockMs()搭配使用
private:
    double m_StartTime;

#ifdef  Q_CC_GNU
    //2.3 程序计时μs
public:
    /** @brief 计时器开始，微秒级别*/
    void startTimerUs();//计时器，与endTimerUs()搭配使用
    /** @brief 计时器结束，微秒级别*/
    double endTimerUs();//计时器，与startTimerUs()搭配使用
private:
    struct timeval m_Start;
    struct timeval m_End;
    double m_Use;

#elif Q_CC_MSVC
    //2.4 程序计时μs
public:
    /** @brief 计时器开始，微秒级别*/
    void startTimerUs();
    /** @brief 计时器结束，微秒级别*/
    double endTimerUs();
private:
    LARGE_INTEGER litmp;
    LONGLONG Qpart1;
    LONGLONG Qpart2;
    LONGLONG Useingtime;
    double dfMinus;
    double dfFreq;
    double dfTime;
#endif
public:
    //3.求和
    /** @brief 两数求和 */
    template<typename Type>
    inline Type sum(const Type &a,const Type &b) //俩个数字求和
    {
        return a+b;
    }
    /** @brief std::vector数组求和 */
    template<typename Type>
    inline Type sum(const std::vector<Type> &data)
    {
        return std::accumulate(data.begin(),data.end(),0.0);
    }

    /** @brief std::list求和 */
    template<typename Type>
    inline Type sum(const std::list<Type> &data)
    {
        return std::accumulate(data.begin(),data.end(),0.0);
    }

    //    /** @brief QVector求和 */
    //    template<typename Type>
    //    inline Type sum(const QVector<Type> &data)
    //    {
    //        return std::accumulate(data.begin(),data.end(),0.0);
    //    }

    /** @brief 数组求和 */
    template<typename Type>
    inline Type sum(Type *data,int size)
    {
        return std::accumulate(data,data+size,0.0);
    }

    //    /** @brief QList求和 */
    //    template<typename Type>
    //    inline Type sum(QList<Type> &data)
    //    {
    //        return std::accumulate(data.begin(),data.end(),0.0);
    //    }

    //4.交换
    /** @brief 两数交换 */
    template<typename Type>
    inline void swap(Type &a,Type &b)
    {
        Type temp = a;
        a = b;
        b = temp;
    }
    //5.平均数
    /** @brief 数组求平均值 */
    template<typename Type>
    inline double average(Type *data,int size)
    {
        return std::accumulate(data,data+size,0.0)/size;
    }

    template<typename Type>
    inline double average(const std::vector<Type> &data)
    {
        return std::accumulate(data.begin(),data.end(),0.0)/data.size();
    }

    template<typename Type>
    inline double average(const std::list<Type> &data)
    {
        return std::accumulate(data.begin(),data.end(),0.0)/data.size();
    }

    //    template<typename Type>
    //    inline double average(const QVector<Type> &data)
    //    {
    //        return std::accumulate(data.begin(),data.end(),0.0)/data.size();
    //    }

    //    template<typename Type>
    //    inline double average(QList<Type> data)
    //    {
    //        return std::accumulate(data.begin(),data.end(),0.0)/data.size();
    //    }

    //6.方差
    /** @brief 数组求方差 */
    template<typename Type>
    inline double variance(Type *data,int size)
    {
        Type average = average(data,size);
        Type sum = 0;
        for (int i = 0; i < size; i++) // 求和
            sum += pow(data[i] - average, 2);
        return sum/size; // 得到方差
    }

    template<typename Type>
    inline double variance(const std::vector<Type> &data)
    {
        int size = data.size();
        Type average = average(data);
        Type sum = 0;
        for (int i = 0; i < size; i++) // 求和
            sum += pow(data[i] - average, 2);
        return sum/size; // 得到方差
    }

    template<typename Type>
    inline double variance(const std::list<Type> &data)
    {
        int size = data.size();
        Type average = average(data);
        Type sum = 0;
        for (int i = 0; i < size; i++) // 求和
            sum += pow(data[i] - average, 2);
        return sum/size; // 得到方差
    }

    //7.标准差
    /** @brief 数组求标准差 */
    template<typename Type>
    inline double standardDev(Type *data,int size)
    {
        Type average = average(data,size);
        Type sum = 0;
        for (int i = 0; i < size; i++) // 求和
            sum += pow(data[i] - average, 2);
        return sqrt(sum/size); // 得到标准差
    }

    template<typename Type>
    inline double standardDev(const std::vector<Type> &data)
    {
        int size = data.size();
        Type average = average(data);
        Type sum = 0;
        for (int i = 0; i < size; i++) // 求和
            sum += pow(data[i] - average, 2);
        return sqrt(sum/size); // 得到标准差
    }

    template<typename Type>
    inline double standardDev(const std::list<Type> &data)
    {
        int size = data.size();
        Type average = average(data);
        Type sum = 0;
        for (int i = 0; i < size; i++) // 求和
            sum += pow(data[i] - average, 2);
        return sqrt(sum/size); // 得到标准差
    }

    //7.中值
    /** @brief 数组求中值 */
    template<typename Type>
    double median(Type *data,int size)
    {
        Type dataCopy[size];
        std::copy(data,data+size,dataCopy);
        std::sort(dataCopy,dataCopy+size);
        Type temp;
        int index;
        if(size%2==0)
        {
            index = size/2;
            temp=(dataCopy[index]+dataCopy[index-1])/2.0;
        }
        else
        {
            index = size/2;
            temp=dataCopy[index];
        }
        return temp;
    }
    template<typename Type>
    double median(const std::vector<Type> &data)
    {
        size_t size = data.size();
        std::vector<Type> dataCopy=data;

        Type temp;
        size_t index;
        if(size%2==0)
        {
            index = size/2;
            temp=(dataCopy[index]+dataCopy[index-1])/2.0;
        }
        else
        {
            index = size/2;
            temp=dataCopy[index];
        }
        return temp;
    }


    template<typename Type>
    inline double median(const std::list<Type> &data)
    {
        int size = data.size();
        std::list<Type> dataCopy=data;
        Type temp;
        int index;
        if(size%2==0)
        {
            index = size/2;
            temp=(dataCopy[index]+dataCopy[index-1])/2.0;
        }
        else
        {
            index = size/2;
            temp=dataCopy[index];
        }
        return temp;
    }

};

}
typedef zgq::ZQFunction zgqf;

#endif // MQFUNCTION_H
